from django.shortcuts import render
from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet  # 只读视图集类
from .serializers import *
from rest_framework.permissions import IsAuthenticated  # 权限
from utils.permission import *
from rest_framework.decorators import action  # 行为路由装饰器
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination  # 分页
from django.db.models import Q  # Q查询

from elasticsearch import Elasticsearch  # es模块
from config.elasticSearchConfig import *
from rest_framework.response import Response

# 创建一个es客户端对象，链接es服务
es = Elasticsearch([{'host': HOST, 'port': PORT}])


class TopicPageNumberPagination(PageNumberPagination):
    page_size = 3  # 每一页有多少条
    page_size_query_param = 'size'  # 控制每页可以有多少数据
    max_page_size = 100  # 最大每页多少条


class TopicLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3  # 默认每一页有多少条
    max_limit = 100  # 最大每页多少条


# Create your views here.
# 用户的视图集
class LabelViewSet(ModelViewSet):
    queryset = Label.objects.all()  # 查询集
    serializer_class = LabelSerializer  # 需要使用的序列化器
    # 要求用户先登录，才能够访问该视图类
    permission_classes = [IsAuthenticated]

    @wrap_permission(TeacherPermission)
    @auto_user
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permission(ActiveUserPPermission)
    @auto_user  # 登录用户的id
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permission(RootPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)


# 题目的视图集
class TopicViewSet(ModelViewSet):
    queryset = Topic.objects.filter(is_delete=False)  # 查询集
    serializer_class = TopicSerializer  # 需要使用的序列化器
    # 要求用户先登录，才能够访问该视图类
    permission_classes = [IsAuthenticated]

    # pagination_class = TopicPageNumberPagination
    pagination_class = TopicLimitOffsetPagination

    # 权限控制
    def get_queryset(self):
        if self.action == 'practice':
            # 没有被删除的题目，标签中没有试卷的标签的题目
            return Topic.objects.filter(Q(is_delete=False) & ~Q(label__name__contains='试卷'))
        return self.queryset

    @wrap_permission(TeacherPermission)
    def list(self, request, *args, **kwargs):
        return ModelViewSet.list(self, request, *args, **kwargs)

    @wrap_permission(ActiveUserPermission)
    def retrieve(self, request, *args, **kwargs):
        return ModelViewSet.retrieve(self, request, *args, **kwargs)

    # 顺序刷题的行为路由
    @action(methods=['get'], detail=False)  # 访问
    def practice(self, request):
        return ModelViewSet.list(self, request)

    # es插入数据行为路由
    @action(methods=['put'], detail=False)  # 访问
    def inites(self, request):
        serializer = self.get_serializer(self.get_queryset(), many=True)
        data = serializer.data

        for i in data:
            # 索引topic，类型_doc，id
            es.index(index='topic', id=i['id'], body=i)

        return Response(data)

    # 查询的行为方法
    @action(methods=['get'], detail=False)  # 访问
    def search(self, request):
        # query = {
        #     "query": {
        #         "match": {
        #             "subject": "Python"
        #         }
        #     },
        #     "highlight": {
        #         "pre_tags": "<span style='color:red'>",
        #         "post_tags": "</span>",
        #         "fields": {
        #             "subject": {}
        #         }
        #     }
        # }
        #
        # es_res = es.search(index='topic', body=query)
        # return Response(es_res)

        # 获取前端的传入的数据
        data = dict(request.query_params)
        subject = data.get('subject', [''])[0]  # 搜索的关键词
        # 分页
        offset = int(data.get('offset', [0])[0])  # from  从第条开始
        limit = int(data.get('limit', [3])[0])  # size  每一页有多少条数据
        user = request.user  # 用户
        group = Group.objects.filter(name='老师').first()  # 老师组对象
        user_groups = user.groups.all()  # zl [老师]
        work_user = user.is_superuser or group in user_groups
        # es语法
        query = {
            "query": {
                # "match": {
                #     "subject": "Python"
                # }
            },
            "highlight": {
                "pre_tags": "<span style='color:red'>",
                "post_tags": "</span>",
                "fields": {
                    "subject": {}
                }
            },
            "from": offset,  # 开始
            "size": limit
        }
        if work_user:
            if subject:
                query["query"]["match"] = {
                    "subject": subject
                }
            else:
                query["query"]["match_all"] = {}

        else:
            if subject:
                query["query"] = {
                    "bool": {
                        "must": [
                            {
                                "match": {
                                    "subject": subject
                                }
                            }
                        ],
                        "must_not": [
                            {
                                "match_phrase": {
                                    "label_name": "试卷"
                                }
                            }
                        ]

                    }
                }
            else:
                query["query"] = {
                    "bool": {
                        "must_not": [
                            {
                                "match_phrase": {
                                    "label_name": "试卷"
                                }
                            }
                        ]
                    }
                }

        es_res = es.search(index='topic', body=query)
        count = es_res["hits"]["total"]["value"]
        # 判断也没有subject参数
        subject_url = f'subject={subject}&' if subject else ''
        # 下一页
        next = f'{CLIENT}/work/topics/search/?{subject_url}limit={limit}&offset={offset+limit}' if offset+limit<count else None
        # 上一页
        previous = f'{CLIENT}/work/topics/search/?{subject_url}limit={limit}&offset={offset-limit}' if offset>0 else None

        # 每条文档数据
        # results = [i["_source"] for i in es_res["hits"]["hits"]]
        results = [self.highlight(i) for i in es_res["hits"]["hits"]]

        res = {
            "count":count,  # 个数
            "next":next,   # 下一页
            "previous":previous,  # 上一页
            "results":results  # 每条文档数据
        }
        return Response(res)
    # 定义一个高亮替换的方法
    def highlight(self,i):
        if i.get('highlight'):
            i["_source"]["subject"] = i["highlight"]["subject"]
        return i["_source"]
